package cn.good.yan.controller.t5;

import cn.good.yan.service.t5.pojo.Product;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * 缓存穿透 - 初始化 查询缓存，避免缓存穿透
 *      新建 ：缓存A主 缓存B从，先更新缓存B，再更新缓存A  缓存B的过期时间大于缓存A
 *      查询： 先查询缓存A，缓存A没有，再查询缓存B、都没有再查询mysql
 * @author shengren.yan
 * @create 2023-11-28
 */
@RestController
@RequestMapping("/ct")
@Slf4j
public class CtController {

    public static final String JHS_KEY = "jhs";
    public static final String JHS_KEY_A = "jhs:a";
    public static final String JHS_KEY_B = "jhs:b";

    @Autowired
    private RedisTemplate redisTemplate;

    // 该方法正常，先查询redis，再查询mysql，存在缓存穿透
    @GetMapping("/findA")
    @ApiOperation("查询商品列表，每次1页每页5条显示")
    public List<Product> findA(int page, int size) {
        List<Product> list = null;
        // 前端第一页传1   ： 0-1 * 5 = 0
        long start = (page - 1) * size;
        long end = start + size - 1;
        try {
            // 采用redis list结构里面的range命令来实现加载和分页
            list = redisTemplate.opsForList().range(JHS_KEY, start, end);
            if (CollectionUtils.isEmpty(list)) {
                // TODO 进行mysql查询
            }
            log.info("参加活动的商家： {}", list);
        } catch (Exception e) {
            // 出异常了，一般redis宕机了或者redis网络抖动导致timeout
            log.error("redis异常{}", e);
            e.printStackTrace();
            // 。。。重试机制 再次查询mysql
        }
        return list;
    }

    // 解决缓存穿透，使用 A缓存、B缓存
    @ApiOperation("AB双缓存架构，防止热点key突然消失")
    public List<Product> findAB(int page, int size) {
        List<Product> list = null;
        long start = (page - 1) * size;
        long end = start + size - 1;
        try {
            // 采用redis list结构里面的range命令来实现加载和分页
            list = redisTemplate.opsForList().range(JHS_KEY_A, start, end);
            if (CollectionUtils.isEmpty(list)) {
                log.info("-----A缓存已经过期或活动结束了，记得人工修补，B缓存继续顶着");
                // A没有来找B
                list = redisTemplate.opsForList().range(JHS_KEY_B, start, end);
                if (CollectionUtils.isEmpty(list)) {
                    // TODO 进行mysql查询
                }
            }
            log.info("参加活动的商家： {}", list);
        } catch (Exception e) {
            // 出异常了，一般redis宕机了或者redis网络抖动导致timeout
            log.error("jhs  redis异常{}", e);
            e.printStackTrace();
            // 。。。重试机制 再次查询mysql
        }
        return list;
    }

}
